package made.ga;

import java.util.Random; // for generating random numbers
import java.util.ArrayList;

import made.util.Config;
import made.util.Logger;

public class ChromosomeFloat implements Config
{
    private ArrayList<Float> _genes;
    private int _size;
    private float _fitness;

    ChromosomeFloat(int size)
    {
        init(size);
    }

    public void init(int size)
    {
        _genes = new ArrayList<Float>(_size);
        _size = size;
        _fitness = 0.0f;

        Random initGenerator = new Random();
        
        for (int i = 0; i < _size; i++)
        {
            // try {
            // Thread.sleep(10);
            // } catch(InterruptedException e) {
            // System.out.println(e);
            // }

//            int tempInt = initGenerator.nextInt(2);
             _genes.add(initGenerator.nextFloat());
//            _genes.add(((float) tempInt));
        }
    }

    public ChromosomeFloat[] reproduce(ChromosomeFloat other)
    {
        ChromosomeFloat[] result = new ChromosomeFloat[2];
        result[0] = new ChromosomeFloat(_size);
        result[1] = new ChromosomeFloat(_size);

        Random crossoverGenerator = new Random();

        int crossoverPoint = crossoverGenerator.nextInt(_size);

        for (int i = 0; i <= crossoverPoint - 1; i++)
        {
            result[0].setGene(i, other.getGene(i));
            result[1].setGene(i, _genes.get(i));

        }

        for (int i = crossoverPoint; i < _size; i++)
        {
            result[0].setGene(i, _genes.get(i));
            result[1].setGene(i, other.getGene(i));
        }

        return result;
    }

    public void mutate()
    {
        
        float valueLimitLower = 0.0f;
        float valueLimitUpper = 1.0f;

        Random mutationProbabilityGenerator = new Random();
        Random mutationOffsetGenerator = new Random();

        for (int i = 0; i < _size; i++)
        {
            if (mutationProbabilityGenerator.nextFloat() < MUTATION_PROBABILITY)
            {
                float mutationOffset = (float) mutationOffsetGenerator.nextGaussian();
                
//                if (GA_DEBUG_LEVEL == DEBUG_LEVEL.VERBOSE)
                    Logger.logLine("MUTATION - added " + mutationOffset + " to " + _genes.get(i) + " = " + (_genes.get(i) + mutationOffset));

                float mutatedValue = _genes.get(i) + mutationOffset;

                if (mutatedValue > valueLimitUpper)
                    mutatedValue = valueLimitUpper;

                if (mutatedValue < valueLimitLower)
                    mutatedValue = valueLimitLower;

                _genes.set(i, mutatedValue);

                // if (_genes.get(i) == 0)
                // {
                // _genes.set(i, 1.0f);
                // } else
                // {
                // _genes.set(i, 0.0f);
                // }
            }
        }
    }

    public void setFitness(float value)
    {
        _fitness = value;
//      IO.logLine("Fitness set to: " + _fitness);
    }

    public float getFitness()
    {
        return _fitness;
    }

    public Float getGene(int index)
    {
        return _genes.get(index);
    }

    public void setGene(int index, Float value)
    {
        if (_genes.size() > index)
            _genes.set(index, value);
        else
            _genes.add(index, value);
    }

//    public String getPhenotype()
//    {
//        // create an empty string
//        String result = "";
//
//        for (int i = 0; i < _size; i++)
//        {
//            // populate it with either A's or a's, depending on the the
//            if (_genes.get(i) == 1)
//            {
//                result += "A";
//            } else
//            {
//                result += "a";
//            }
//        }
//        return result;
//    }
    
    public ArrayList<Float> getPhenotype()
    {
        return _genes;
    }

    public String toString()
    {
        String str = "";

        for (int i = 0; i < _size; i++)
        {
            if (i != _size - 1)
                str += _genes.get(i) + " ";
            else
                str += _genes.get(i);
        }

        return str;
    }
};